package com.lovezy.platform.play.scene.service.impl;

import com.github.pagehelper.Page;
import com.lovezy.platform.core.base.enums.StatusEnum;
import com.lovezy.platform.core.base.enums.TrueOrFalseEnum;
import com.lovezy.platform.core.base.query.Pager;
import com.lovezy.platform.core.base.service.MapperService;
import com.lovezy.platform.core.exception.ServiceException;
import com.lovezy.platform.play.model.PlayCharacterSkill;
import com.lovezy.platform.play.scene.mapper.PlaySceneCharacterSkillMapper;
import com.lovezy.platform.play.scene.model.PlaySceneCharacter;
import com.lovezy.platform.play.scene.model.PlaySceneCharacterSkill;
import com.lovezy.platform.play.scene.model.PlaySceneCharacterSkillExample;
import com.lovezy.platform.play.scene.vo.SimpleSkillMeta;
import com.lovezy.platform.play.scene.vo.SkillSimpleInfo;
import com.lovezy.platform.play.service.PlayCharacterSkillService;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;

import static com.lovezy.platform.core.utils.ObjectUtil.byteToBoolean;
import static java.util.stream.Collectors.toList;

/**
 * Created by jin on 2018/1/30.
 */
@Service
public class PlaySceneCharacterSkillService extends MapperService<PlaySceneCharacterSkill,Integer,PlaySceneCharacterSkillMapper>{

    @Autowired
    PlayCharacterSkillService playCharacterSkillService;

    @Autowired
    PlaySceneCharacterService playSceneCharacterService;

    @Autowired
    PlaySceneLogService playSceneLogService;

    public List<SimpleSkillMeta> simpleMeta(Integer sceneId) {
        return Pager.doPageAll(() -> mapper.simpleMeta(sceneId));
    }

    public List<SkillSimpleInfo> findSkillSimpleInfoBySceneCharId(Integer sceneCharacterId) {
        PlaySceneCharacterSkillExample example = new PlaySceneCharacterSkillExample();
        example.createCriteria()
                .andSceneCharacterIdEqualTo(sceneCharacterId)
                .andStatusEqualTo(StatusEnum.NORMAL.value());
        Page<PlaySceneCharacterSkill> skiils = Pager.doPageAll(() -> mapper.selectByExample(example));
        return skiils.stream()
                .map(s -> {
                    SkillSimpleInfo skillSimpleInfo = new SkillSimpleInfo();
                    skillSimpleInfo.setSkillId(s.getSkillId());
                    skillSimpleInfo.setEnable(byteToBoolean(s.getEnableStatus()));
                    return skillSimpleInfo;
                }).collect(toList());
    }


    public void copyCharacterSkill(List<PlaySceneCharacter> characters) {
        characters.parallelStream()
                .flatMap(c -> {
                    List<PlayCharacterSkill> characterSkills = playCharacterSkillService.findCharacterSkills(c.getCharacterId());
                    Integer sceneCharacterId = c.getSceneCharacterId();
                    Integer sceneId = c.getSceneId();
                    return characterSkills.stream().map(cs -> {
                        PlaySceneCharacterSkill skill = new PlaySceneCharacterSkill();
                        skill.setSceneCharacterId(sceneCharacterId);
                        skill.setSkillId(cs.getSkillId());
                        skill.setEnableStatus(TrueOrFalseEnum.TRUE.value());
                        skill.setStatus(cs.getStatus());
                        skill.setSceneId(sceneId);
                        return skill;
                    });
                }).forEach(mapper::insert);

    }

    @Transactional
    public void transfer(Integer sceneId, @Nullable Integer fromSceneCharId, @NotNull Integer toSceneCharId, @NotNull Integer skillId) {
        boolean hasFrom = fromSceneCharId != null;
        if (hasFrom) {
            Optional<PlaySceneCharacterSkill> itemOptional = hasThisSkill(fromSceneCharId, skillId);
            if (!itemOptional.isPresent()) {
                throw new ServiceException("没有此技能");
            }
            PlaySceneCharacterSkill sceneCharacterSkill = itemOptional.get();
            sceneCharacterSkill.setStatus(StatusEnum.DELETED.value());
            mapper.updateByPrimaryKeySelective(sceneCharacterSkill);
        }

        newSkill(sceneId, toSceneCharId, skillId);
        PlayCharacterSkill characterSkill = playCharacterSkillService.findById(skillId, true);
        transferLog(sceneId, fromSceneCharId, toSceneCharId, characterSkill.getName());
    }

    private void transferLog(Integer sceneId,Integer fromSceneCharacterId,Integer toSceneCharacterId,String skillName) {
        String contentTemplate;
        Integer[] characterIds;
        PlaySceneCharacter to = playSceneCharacterService.findCharacter(sceneId, toSceneCharacterId);
        if (fromSceneCharacterId != null) {
            PlaySceneCharacter from = playSceneCharacterService.findCharacter(sceneId, fromSceneCharacterId);
            contentTemplate = "%s从%s处得到了技能" + skillName;
            characterIds = new Integer[]{from.getCharacterId(), to.getCharacterId()};
        }else{
            contentTemplate = "%s得到了技能" + skillName;
            characterIds = new Integer[]{to.getCharacterId()};
        }
        playSceneLogService.logSceneWithCharacter(sceneId, contentTemplate, characterIds);

    }

    public void change(Integer sceneId, Integer sceneCharId, Integer skillId,StatusEnum status,TrueOrFalseEnum enable) {
        PlaySceneCharacterSkillExample example = new PlaySceneCharacterSkillExample();
        example.createCriteria()
                .andSceneIdEqualTo(sceneId)
                .andSceneCharacterIdEqualTo(sceneCharId)
                .andSkillIdEqualTo(skillId);
        PlaySceneCharacterSkill update = new PlaySceneCharacterSkill();
        update.setStatus(status.value());
        update.setEnableStatus(enable.value());
        mapper.updateByExampleSelective(update, example);
    }

    private Optional<PlaySceneCharacterSkill> hasThisSkill(Integer charId, Integer skillId) {
        PlaySceneCharacterSkillExample example = new PlaySceneCharacterSkillExample();
        example.createCriteria()
                .andSceneCharacterIdEqualTo(charId)
                .andSkillIdEqualTo(skillId);
        return Pager.doSingleton(() -> mapper.selectByExample(example));
    }

    private PlaySceneCharacterSkill newSkill(Integer sceneId, Integer sceneCharId, Integer skillId) {
        PlaySceneCharacterSkill skill = new PlaySceneCharacterSkill();
        skill.setSceneCharacterId(sceneCharId);
        skill.setEnableStatus(TrueOrFalseEnum.TRUE.value());
        skill.setStatus(StatusEnum.NORMAL.value());
        skill.setSkillId(skillId);
        skill.setSceneId(sceneId);
        mapper.insert(skill);
        return skill;
    }

}
